package advanced.network.demo;


import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;

/**
 * 在线聊天室: 服务端
 * <p>
 * 服务器端只负责转发消息
 */
public class ChatServer {
    private static Map<Integer, Channel> users = new HashMap<Integer, Channel>();

    public static void main(String[] args) throws IOException {
        ServerSocket server = new ServerSocket(8888);
        while (true) {
            Socket client = server.accept();//阻塞式接收的
            Channel channel = new Channel(client, users);
            //如果不在聊天组里 则加入
            if (!users.containsKey(client.getPort())) {

                users.put(client.getPort(), channel);
                System.out.println("一个客户端建立了连接");
            }
            new Thread(new Channel(client, users)).start();
        }
    }
}

class Channel implements Runnable {
    private Socket client;
    private DataInputStream dis = null;
    private DataOutputStream dos = null;
    private boolean isRunning = true;
    private Map<Integer, Channel> users;

    public Channel(Socket client, Map<Integer, Channel> users) {
        this.users = users;
        this.client = client;
    }

    /**
     * 发送消息
     *
     * @param dataGram
     */
    public void send(String dataGram) throws IOException {
        dos = new DataOutputStream(client.getOutputStream());
        dos.writeUTF(dataGram);
        dos.flush();

    }

    /**
     * 接收消息
     *
     * @return
     */
    public String receive() throws IOException {
        String dataGram = "";
        dis = new DataInputStream(client.getInputStream());
        dataGram = dis.readUTF();

        return dataGram;
    }

    public void release(boolean closeClient) {
        this.isRunning = false;
        if (dis != null) {
            try {
                dis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (dos != null) {
            try {
                dos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (closeClient)
            if (!client.isClosed()) {
                try {
                    client.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
    }

    @Override
    public void run() {
        while (isRunning) {
            try {
                String dataGram = receive();
                int tarUser = -1;
                String msg = dataGram;
                System.out.println("msg from client=" + dataGram);
                if (dataGram.contains("@")) {
                    if (dataGram.startsWith("@")) {
                        System.out.println("群消息");
                        for (Map.Entry<Integer, Channel> entry : users.entrySet()) {
                            if (client != entry.getValue().getClient())
                                entry.getValue().send(dataGram.substring(1));
                        }
                    } else {
                        String[] split = dataGram.split("@");
                        try {
                            tarUser = Integer.valueOf(split[0]);
                        } catch (Exception e) {
                            send("请正确指定用户的通讯ID, 只包含数字");
                        }
                        msg = split[1];
                        if (users.containsKey(tarUser)) {
                            Socket tarClient = users.get(tarUser).getClient();
                            new Channel(tarClient, users).send(msg);
                        } else {
                            send("该用户不存在,请检查");
                        }
                    }

                } else
                    send("请指定接收人 格式为: ***@消息内容");
            } catch (IOException e) {
                e.printStackTrace();
                isRunning = false;
            }

        }
    }

    public Socket getClient() {
        return this.client;
    }
}
